﻿using Ndns.ServerHost.Abstractions;
using Ndns.ServerHost.Abstractions.Services;
using Ndns.ServerHost.Services;
using Ndns.ServerHost.Stubs;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Ndns.ServerHost.Builder
{
    public class DnsServerHostBuilder : IDnsServerHostBuilder
    {
        private List<Action<IMiddlewaresBuilder>> _configureMiddlewareDelegates = new List<Action<IMiddlewaresBuilder>>();
        private List<Action<IServiceBuilder>> _configureServicesDelegates = new List<Action<IServiceBuilder>>();

        public IDnsServerHostBuilder ConfigureMiddlewares(Action<IMiddlewaresBuilder> builderDelegate)
        {
            if (builderDelegate == null)
                throw new ArgumentNullException(nameof(builderDelegate));
            _configureMiddlewareDelegates.Add(builderDelegate);
            return this;
        }

        public IDnsServerHostBuilder ConfigureServices(Action<IServiceBuilder> builderDelegate)
        {
            if (builderDelegate == null)
                throw new ArgumentNullException(nameof(builderDelegate));
            _configureServicesDelegates.Add(builderDelegate);
            return this;
        }

        public IDnsServerHost Build()
        {
            // 初始化服务集合
            var serviceCollection = new ServiceCollectionImpl();
            var serviceBuilder = new ServiceBuilderImpl(serviceCollection);
            BuildDefaultServices(serviceBuilder);
            foreach (var eachServiceConfig in _configureServicesDelegates)
            {
                eachServiceConfig(serviceBuilder);
            }

            // 注册服务
            MethodInfo targetMethod;
            var targetParam = new object[1] { serviceCollection };
            foreach (var serviceInfo in serviceCollection)
            {
                var serivce = serviceInfo.Value;

                targetMethod = null;
                var typeInfo = serivce.GetType().GetTypeInfo();
                var methods = typeInfo.GetDeclaredMethods("RegisterServices");
                foreach (var method in methods)
                {
                    if (!method.IsPublic)
                    {
                        continue;
                    }
                    var parameters = method.GetParameters();
                    if (parameters.Length != 1)
                    {
                        continue;
                    }
                    if (parameters[0].IsOut)
                    {
                        continue;
                    }
                    if (!parameters[0].ParameterType.Equals(typeof(IServiceCollection)))
                    {
                        continue;
                    }

                    targetMethod = method;
                }

                if (targetMethod != null)
                {
                    targetMethod.Invoke(serivce, targetParam);
                }
            }

            // 初始化中间件列表
            var middlewares = new List<IMiddleware>();
            var middlewareBuilder = new MiddlewaresBuilder(middlewares);
            foreach (var eachMiddlewareConfig in _configureMiddlewareDelegates)
            {
                eachMiddlewareConfig(middlewareBuilder);
            }

            // 构建调用链表
            MiddlewareNode head = middlewares.Count > 0 ? new MiddlewareNode(middlewares[0]) : null;
            MiddlewareNode current = head;
            for (int i = 1; i < middlewares.Count; i++)
            {
                current.Next = new MiddlewareNode(middlewares[i]);
                current = current.Next;
            }

            return new DnsServerHost(serviceCollection, head);
        }

        private static void BuildDefaultServices(IServiceBuilder builder)
        {
            builder.Add<ILoggerProvider>(new StubLoggerProvider());
        }
    }
}
